package com.thb.pay.core.interceptor;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.thb.pay.core.bean.SysLogEntity;
import com.thb.pay.core.holder.LogContextHolder;
import com.thb.pay.core.logs.utils.LogConstants;
import com.thb.pay.core.utils.DateUtil;
import com.thb.pay.core.utils.IpInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.slf4j.MDC;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.UUID;

@Slf4j
public class LogRequestProcessInterceptor implements HandlerInterceptor {


    protected String getLogRequestId(HttpServletRequest request, HttpServletResponse response) {
        String logRequestId = request.getHeader(LogConstants.LOG_REQ_ID);
        if (StringUtils.isEmpty(logRequestId)) {
            logRequestId = UUID.randomUUID().toString().replace("-", "");
        }
        response.setHeader(LogConstants.LOG_REQ_ID, logRequestId);
        return logRequestId;
    }

    protected String getLogRequestTimeId(HttpServletRequest request, HttpServletResponse response) {
        String reqTimeId = request.getHeader(LogConstants.REQ_TIME_ID);
        if (StringUtils.isEmpty(reqTimeId)) {
            reqTimeId = String.valueOf(System.currentTimeMillis());
        }
        response.setHeader(LogConstants.REQ_TIME_ID, reqTimeId);
        return reqTimeId;
    }

    protected void addRequestTagLog(HttpServletRequest request, HttpServletResponse response) {
        //创建请求实体
        SysLogEntity loggerEntity = new SysLogEntity();
        //获取请求的sessionId
        String sessionId = request.getRequestedSessionId();
        //请求的路径
        String path = request.getRequestURI();
        //获取请求参数信息
        String paramData = JSON.toJSONString(request.getParameterMap(), SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue);
        //设置客户端ip
        loggerEntity.setIp(IpInfoUtil.getIp(request));
        //设置请求方法
        loggerEntity.setMethod(request.getMethod());
        //设置请求类型
        loggerEntity.setType(request.getHeader("X-Requested-With"));
        //设置请求参数的json字符串
        loggerEntity.setParams(paramData);
        //设置请求地址
        loggerEntity.setUri(path);
        //设置sessionId
        loggerEntity.setSessionId(sessionId);
        //设置请求开始时间
        request.setAttribute(LogConstants.REQ_TIME_ID, System.currentTimeMillis());
        //设置请求实体到request中，方便after调用
        request.setAttribute(LogConstants.LOGGER_ENTITY, loggerEntity);


    }

    protected void addResponseTagLog(HttpServletRequest request, HttpServletResponse response) {
        //获取请求错误码
        int status = response.getStatus();
        Date currentDate = new Date();
        //当前时间
        long currentTime = currentDate.getTime();
        //请求开始时间
        long time = Long.parseLong(request.getAttribute(LogConstants.REQ_TIME_ID).toString());
        //获取本次请求日志实体
        SysLogEntity loggerEntity = (SysLogEntity) request.getAttribute(LogConstants.LOGGER_ENTITY);
        //设置请求时间差
        loggerEntity.setTimeConsuming(Integer.valueOf(String.valueOf((currentTime - time))));
        //设置返回时间
        loggerEntity.setReturnTime(currentDate);
        //设置返回错误码
        loggerEntity.setHttpStatusCode(String.valueOf(status));
        loggerEntity.setReturnData(JSON.toJSONString(request.getAttribute(LogConstants.LOGGER_RETURN), SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue));
        //设置返回值
        log.debug("log.request.end: url:{}, responseData:{}, cost.time: {} ms", request.getRequestURL(), loggerEntity.getReturnData(), loggerEntity.getTimeConsuming());

    }

    public void preAddRequestTagLog(HttpServletRequest request, HttpServletResponse response) {
        this.addRequestTagLog(request, response);
        String requestMethodName = request.getServletPath();
        String tempMethod = requestMethodName.replace("/", "_");
        String logReqId = getLogRequestId(request, response);
        String reqTimeId = getLogRequestTimeId(request, response);
        MDC.put(LogConstants.LOG_REQ_ID, logReqId);
        MDC.put(LogConstants.REQ_TIME_ID, reqTimeId);
        MDC.put(LogConstants.MAIN_THREAD_ID, String.valueOf(Thread.currentThread().getId()));
        MDC.put(LogConstants.MDC_ACTION, String.format("method%s", tempMethod));

        MDC.put(LogConstants.FILE_KEY, String.format("%s/%s/%s/method%s/method%s.%s", DateUtil.getYear(new Date()), DateUtil.getMonth(new Date()), DateUtil.getDay(new Date()), tempMethod, tempMethod, logReqId));
        LogContextHolder.setLogReqId(logReqId);
        LogContextHolder.setReqTimeId(Long.valueOf(reqTimeId));


        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String query = request.getQueryString();
        log.debug("log.request.receive: url:{},method:{},query:{}, reqData:{}", url, method, query, JSON.toJSONString(request.getAttribute(LogConstants.LOGGER_ENTITY)));
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        this.preAddRequestTagLog(request, response);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        try {
            this.addResponseTagLog(request, response);
            String logReqId = LogContextHolder.getLogReqId();
            if (StringUtils.isNotEmpty(logReqId)) {
                response.setHeader(LogConstants.LOG_REQ_ID, logReqId);
            }
        } finally {
            LogContextHolder.removeCurrentContextMap();
            MDC.clear();
        }
    }

}
